/**
 *Copyright [2010] [lcj(caijunlu@gmail.com)]
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License. 
 *You may obtain a copy of the License at 
 *             http://www.apache.org/licenses/LICENSE-2.0 
 *Unless required by applicable law or agreed to in writing, 
 *software distributed under the License is distributed on an "AS IS" BASIS, 
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 
 *either express or implied. See the License for the specific language governing permissions and limitations under the License
 */
package org.independent.servlet.session.util.kyro;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.serialize.ArraySerializer;
import com.esotericsoftware.kryo.serialize.BigDecimalSerializer;
import com.esotericsoftware.kryo.serialize.BigIntegerSerializer;
import com.esotericsoftware.kryo.serialize.BooleanSerializer;
import com.esotericsoftware.kryo.serialize.ByteSerializer;
import com.esotericsoftware.kryo.serialize.CharSerializer;
import com.esotericsoftware.kryo.serialize.CollectionSerializer;
import com.esotericsoftware.kryo.serialize.CompatibleFieldSerializer;
import com.esotericsoftware.kryo.serialize.DateSerializer;
import com.esotericsoftware.kryo.serialize.DoubleSerializer;
import com.esotericsoftware.kryo.serialize.EnumSerializer;
import com.esotericsoftware.kryo.serialize.FieldSerializer;
import com.esotericsoftware.kryo.serialize.FloatSerializer;
import com.esotericsoftware.kryo.serialize.IntSerializer;
import com.esotericsoftware.kryo.serialize.LongSerializer;
import com.esotericsoftware.kryo.serialize.MapSerializer;
import com.esotericsoftware.kryo.serialize.ShortSerializer;
import com.esotericsoftware.kryo.serialize.StringSerializer;

/**
 * Register the object include all the classes and interfaces to the Kryo
 * 
 * @author lcj
 * 
 */
public class RegisterSerializers {

	final static private Map<String, Integer> classNameIntMappings = new HashMap<String, Integer>();

	final static public void registerAllClass(Kryo kryo, List<Class<?>> classes) {
		for (Class<?> clazz : classes) {
			registerClass(kryo, clazz);
		}
	}

	@SuppressWarnings("unchecked")
	final public static void registerClass(Kryo kryo, Class<?> clazz) {
		if (clazz.isArray()) {
			kryo.register(clazz, new ArraySerializer(kryo));
		}
		final String name = clazz.getName();
		switch (classNameIntMappings.get(name) == null ? 99
				: classNameIntMappings.get(name)) {
		case 1:
			kryo.register(int.class, new IntSerializer());
			kryo.register(Integer.class, new IntSerializer());
			break;

		case 2:
			kryo.register(double.class, new DoubleSerializer());
			kryo.register(Double.class, new DoubleSerializer());
			break;

		case 3:
			kryo.register(long.class, new LongSerializer());
			kryo.register(Long.class, new LongSerializer());
			break;

		case 4:
			kryo.register(boolean.class, new BooleanSerializer());
			kryo.register(Boolean.class, new BooleanSerializer());
			break;

		case 5:
			kryo.register(float.class, new FloatSerializer());
			kryo.register(Float.class, new FloatSerializer());
			break;

		case 6:
			kryo.register(char.class, new CharSerializer());
			break;

		case 7:
			kryo.register(byte.class, new ByteSerializer());
			kryo.register(Byte.class, new ByteSerializer());
			break;

		case 8:
			kryo.register(short.class, new ShortSerializer());
			kryo.register(Short.class, new ShortSerializer());
			break;

		case 9:
			kryo.register(java.lang.reflect.Array.class,
					new ArraySerializer(kryo));
			break;

		case 11:
			kryo.register(java.math.BigDecimal.class,
					new BigDecimalSerializer());
			break;

		case 12:
			kryo.register(java.math.BigInteger.class,
					new BigIntegerSerializer());
			break;

//			case 13:
//				kryo.register(java.lang.Class.class, new ClassSerializer(kryo));
//				break;

		case 14:
			kryo.register(clazz, new CollectionSerializer(kryo));
			break;

		case 15:
			kryo.register(clazz, new CompatibleFieldSerializer(kryo, clazz));
			break;

		case 16:
			kryo.register(java.util.Date.class, new DateSerializer());
			break;

		case 17:
			kryo.register(clazz, new EnumSerializer(
					(Class<? extends Enum<?>>) clazz));
			break;

		case 18:
			MapSerializer ms = new MapSerializer(kryo);
			ms.setKeysCanBeNull(false);
			ms.setValuesCanBeNull(false);
			kryo.register(clazz, ms);
			break;

		case 19:
			kryo.register(String.class, new StringSerializer());
			break;

		case 99:
			kryo.register(clazz, new FieldSerializer(kryo, clazz));
			break;
		}
	}

	static {
		classNameIntMappings.put("int", 1);
		classNameIntMappings.put("java.lang.Integer", 1);
		classNameIntMappings.put("double", 2);
		classNameIntMappings.put("java.lang.Double", 2);
		classNameIntMappings.put("long", 3);
		classNameIntMappings.put("java.lang.Long", 3);
		classNameIntMappings.put("boolean", 4);
		classNameIntMappings.put("java.lang.Boolean", 4);
		classNameIntMappings.put("float", 5);
		classNameIntMappings.put("java.lang.Float", 5);
		classNameIntMappings.put("char", 6);
		classNameIntMappings.put("byte", 7);
		classNameIntMappings.put("java.lang.Byte", 7);
		classNameIntMappings.put("short", 8);
		classNameIntMappings.put("java.lang.Short", 8);
		classNameIntMappings.put("java.lang.reflect.Array", 9);
		classNameIntMappings.put("java.math.BigDecimal", 11);
		classNameIntMappings.put("java.math.BigInteger", 12);
//		classNameIntMappings.put("java.lang.Class", 13);
		classNameIntMappings.put("java.util.Collection", 14);
		classNameIntMappings.put("java.util.Comparatort", 15);
		classNameIntMappings.put("java.util.Date", 16);
		classNameIntMappings.put("java.lang.Enum", 17);
		classNameIntMappings.put("java.util.Map", 18);
		classNameIntMappings.put("java.lang.String", 19);
	}
}
